package com.chalk.config.security.filter;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Iterator;

/**
 * ClassName: CustomAccessDecisionManager
 * 此类是决策器： 用来对 用户应有的角色,与URL地址可以访问的角色进行对比,如果不匹配则抛出异常
 *
 * @author L.G
 * @Description 自定义 AccessDecisionManager
 * @email lg10000@126.com
 * @date 2018年8月27日 下午4:34:07
 */
@Component
public class CustomAccessDecisionManager implements AccessDecisionManager {

    /**
     * decide 方法是判定是否拥有权限的决策方法
     * authentication 是释CustomUserService中循环添加到 GrantedAuthority对象中的权限信息集合.
     * object 包含客户端发起的请求的requset信息，可转换为 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
     * configAttributes 为CustomInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果，此方法是为了判定用户请求的url是否在权限表中，如果在权限表中，则返回给decide方法，用来判定用户是否有此权限。如果不在权限表中则放行。
     */
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
        if (null == configAttributes || configAttributes.size() <= 0) {
            throw new AccessDeniedException("权限不足");
        }
        Iterator<ConfigAttribute> iterator = configAttributes.iterator();
        Iterator<? extends GrantedAuthority> author = authentication.getAuthorities().iterator();
        while (iterator.hasNext()) {
            ConfigAttribute configAttribute = (ConfigAttribute) iterator.next();
            while (author.hasNext()) {
                GrantedAuthority grantedAuthority = (GrantedAuthority) author.next();
                if (configAttribute.getAttribute().equals(grantedAuthority.getAuthority())) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("权限不足");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

}
